package cn.xlbweb.cli.shiro;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.ehcache.EhCacheManager;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author: bobi
 * @date: 2020-04-11 23:41
 * @description:
 */
@Slf4j
public class CliCredentialsMatcher extends HashedCredentialsMatcher {

    private int maxRetryNum = 5;

    public void setMaxRetryNum(int maxRetryNum) {
        this.maxRetryNum = maxRetryNum;
    }

    private EhCacheManager ehCacheManager;

    public CliCredentialsMatcher(EhCacheManager ehCacheManager) {
        this.ehCacheManager = ehCacheManager;
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        Cache<String, AtomicInteger> passwordRetryCache = ehCacheManager.getCache("passwordRetryCache");
        String username = token.getPrincipal().toString();
        AtomicInteger retryCount = passwordRetryCache.get(username);
        if (retryCount == null) {
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(username, retryCount);
        }
        if (retryCount.incrementAndGet() >= maxRetryNum) {
            log.warn("账号{}在规定时间内已经尝试登录{}次失败", username, maxRetryNum);
            throw new ExcessiveAttemptsException("账号" + username + "在规定时间内已经尝试登录" + maxRetryNum + "次失败");
        }
        boolean matches = super.doCredentialsMatch(token, info);
        if (matches) {
            passwordRetryCache.remove(username);
        }
        return matches;
    }
}
